﻿using System;
using System.IO;
using CoreTypes;
using System.Linq;
using System.Custom;
using System.Drawing;
using Microsoft.Win32;
using System.Reflection;
using System.Globalization;
using System.Custom.Window;
using System.Windows.Forms;
using System.ComponentModel;
using MainModule.Properties;
using System.Collections.Generic;

namespace MainModule
{
   public partial class SettingsWindow : Window
   {
      #region Window Data

      bool FNeedRestart;
      bool FAssigningPrivacy;
      InternetCommunicator FCommunicator = InternetCommunicator.Self;

      #endregion

      public SettingsWindow()
      {
         InitializeComponent();

         Settings.Default.PropertyChanged += settings_PropertyChanged;
         FCommunicator.PropertyChanged += communicator_PropertyChanged;
         FCommunicator.InstallationCheck += communicator_CheckingUpdates;
         foreach (var svc in FCommunicator.ServiceDrivers) svc.SettingsChanged += service_SettingsChanged;

         Height = MinimumSize.Height;

         window_AeroGlassEffectChanged(null, null);

         profileManager.Initialize();

         dataTablePolicyValues.Rows.Add(PolicyRule.Allow, Resources.S_Start_session);
         dataTablePolicyValues.Rows.Add(PolicyRule.Ask, Resources.S_Ask_me);
         dataTablePolicyValues.Rows.Add(PolicyRule.Block, Resources.S_Block);
         dataTablePolicyValues.Rows.Add(PolicyRule.Ignore, Resources.S_Ignore);

         dataTableLayoutValues.Rows.Add(WindowDockType.ClassicWindowNormal, Resources.S_Classic_normal);
         dataTableLayoutValues.Rows.Add(WindowDockType.ClassicWindowLarge, Resources.S_Classic_large);
         dataTableLayoutValues.Rows.Add(WindowDockType.FloatPanel, Resources.S_Floating_panel);

         dataTableRenderValues.Rows.Add(ToolStripRenderMode.System, Resources.S_Classic);
         dataTableRenderValues.Rows.Add(ToolStripRenderMode.Professional, Resources.S_Standard);

         dataTableFillStyleValues.Rows.Add(ColorFillStyle.Plastic, Resources.S_Plastic);
         dataTableFillStyleValues.Rows.Add(ColorFillStyle.Glass, Resources.S_Glass);

         dataTableSortStyleValues.Rows.Add(ContactsSortStyle.Caption, Resources.S_By_name);
         dataTableSortStyleValues.Rows.Add(ContactsSortStyle.CaptionWidth, Resources.S_By_name_width);

         Icon = (Icon)ResourceWrapper.GetObject("Gear");

         comboBoxMainWindowSide.Items.Add(Resources.S_Screen_left);
         comboBoxMainWindowSide.Items.Add(Resources.S_Screen_right);

         comboBoxLanguage.Items.AddRange(FCommunicator.SupportedCultures);

         //foreach (CultureInfo culture in FCommunicator.NeutralCultures)
         //{
         //   MenuItem cultureItem = new MenuItem(culture.DisplayName, menuItemInstallCulture_Click);
         //   cultureItem.Tag = culture;
         //   contextMenuCultureList.MenuItems.Add(cultureItem);

         //   IEnumerable<CultureInfo> subCultures = FCommunicator.SpecificCultures.Where(c => c.TwoLetterISOLanguageName == culture.TwoLetterISOLanguageName);
            
         //   if (subCultures.Count() > 1)
         //   {
         //      MenuItem defCultureItem = new MenuItem(culture.DisplayName, menuItemInstallCulture_Click);
         //      defCultureItem.Tag = culture;
         //      cultureItem.MenuItems.Add(defCultureItem);

         //      cultureItem.MenuItems.Add("-");

         //      foreach (CultureInfo subCulture in subCultures)
         //      {
         //         MenuItem subCultureItem = new MenuItem(subCulture.DisplayName, menuItemInstallCulture_Click);
         //         subCultureItem.Tag = subCulture;
         //         cultureItem.MenuItems.Add(subCultureItem);
         //      }
         //   }
         //   else if (subCultures.Count() == 1)
         //   {
         //      CultureInfo subCulture = subCultures.First();
         //      cultureItem.Text = subCulture.DisplayName;
         //      cultureItem.Tag = subCulture;
         //   }
         //}

         comboBoxLogStyle.Items.AddRange(FCommunicator.PredefinedLogStyles.ToArray());
         comboBoxLogStyle.Items.Add(Resources.S_Custom);
      }

      protected override void Dispose(bool disposing)
      {
         Settings.Default.PropertyChanged -= settings_PropertyChanged;
         FCommunicator.PropertyChanged -= communicator_PropertyChanged;
         FCommunicator.InstallationCheck -= communicator_CheckingUpdates;
         foreach (var svc in FCommunicator.ServiceDrivers) svc.SettingsChanged -= service_SettingsChanged;

         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      public void Show(string page)
      {
         tabControl.SelectedTab = tabControl.TabPages.ContainsKey("tabPage" + page) ?
                                    tabControl.TabPages["tabPage" + page] :
                                    tabControl.TabPages["tabPageGeneral"];
         AssignSettings();

         Visualize();
      }

      public override ColorTheme ColorTheme
      {
         get
         {
            return base.ColorTheme;
         }
         set
         {
            base.ColorTheme = value;
            Refresh();
         }
      }

      private void ApplySettings()
      {
         #region Registry

         try
         {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);

            if (checkBoxRunWithSystem.Checked)
            {
               key.SetValue(FCommunicator.AppName, Assembly.GetExecutingAssembly().Location + " /a");
            }
            else
            {
               key.DeleteValue(FCommunicator.AppName, false);
            }

            key.Close();
         }
         catch
         {
            //
         }

         #endregion

         string cultureName = (comboBoxLanguage.SelectedItem as CultureInfo).Name;

         if (cultureName != Settings.Default.Culture)
         {
            FNeedRestart = true;
            Settings.Default.Culture = cultureName;
         }

         Settings.Default.SendOn = (string)comboBoxSendOn.SelectedItem;
         Settings.Default.ProxyType = (string)comboBoxProxy.SelectedItem;
         Settings.Default.NATimeout = !checkBoxNaTimeout.Checked || comboBoxNaTimeout.Text == "" ? 0 : int.Parse(comboBoxNaTimeout.Text);
         Settings.Default.AwayTimeout = !checkBoxAwayTimeout.Checked || comboBoxAwayTimeout.Text == "" ? 0 : int.Parse(comboBoxAwayTimeout.Text);
      }
      private void AssignPrivacy()
      {
         FAssigningPrivacy = true;

         try
         {
            checkBoxMessageRuleBlock.Checked = Settings.Default.UnknownUserMessageRule == PolicyRule.Block;
            checkBoxInvitationRuleBlock.Checked = Settings.Default.UnknownUserInvitationRule == PolicyRule.Block;

            comboBoxUnknownUserMessageRule.SelectedValue = Settings.Default.UnknownUserMessageRule;
            comboBoxUnknownUserInvitationRule.SelectedValue = Settings.Default.UnknownUserInvitationRule;
            comboBoxMyContactsMessageRule.SelectedValue = Settings.Default.MyContactMessageRule;
            comboBoxMyContactsInvitationRule.SelectedValue = Settings.Default.MyContactInvitationRule;
            comboBoxVipInvitationRule.SelectedValue = Settings.Default.VipContactInvitationRule;
         }
         finally
         {
            FAssigningPrivacy = false;
         }
      }
      private void AssignSettings()
      {
         #region Registry

         try
         {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");

            checkBoxRunWithSystem.Checked = key.GetValue(FCommunicator.AppName, "").ToString().StartsWith(Assembly.GetExecutingAssembly().Location);

            key.Close();
         }
         catch
         {
            checkBoxRunWithSystem.Checked = false;
         }

         #endregion

         comboBoxLanguage.SelectedItem = FCommunicator.Culture;
         if (comboBoxLanguage.SelectedItem == null) comboBoxLanguage.SelectedItem = FCommunicator.Culture.Parent;
         labelSearchCultureResults.Visible = false;
         labelSearchCultureResults.ForeColor = Color.DimGray;

         if (Settings.Default.AwayTimeout > 0)
         {
            checkBoxAwayTimeout.Checked = true;
            comboBoxAwayTimeout.Text = Settings.Default.AwayTimeout.ToString();
         }
         else
         {
            checkBoxAwayTimeout.Checked = false;
            comboBoxAwayTimeout.Text = Settings.Default.Properties["AwayTimeout"].DefaultValue.ToString();
         }

         if (Settings.Default.NATimeout > 0)
         {
            checkBoxNaTimeout.Checked = true;
            comboBoxNaTimeout.Text = Settings.Default.NATimeout.ToString();
         }
         else
         {
            checkBoxNaTimeout.Checked = false;
            comboBoxNaTimeout.Text = Settings.Default.Properties["NATimeout"].DefaultValue.ToString();
         }

         comboBoxSendOn.SelectedItem = Settings.Default.SendOn;
         buttonInputFont.Text = Settings.Default.InputFont + "; " + Settings.Default.InputFontSize + "pt";
         comboBoxLogStyle.SelectedItem = Settings.Default.SelectedLogStyleName;

         comboBoxSortStyle.SelectedValue = Settings.Default.ContactsSortStyle;
         comboBoxMainWindowLayout.SelectedValue = Settings.Default.MainWindowLayout;
         comboBoxMainWindowSide.SelectedIndex = Settings.Default.MainWindowLeftSide ? 0 : 1;

         dataTableColorThemes.Clear();
         dataTableColorThemes.Rows.Add(DBNull.Value, "<No theme>");
         foreach (var theme in InternetCommunicator.Self.ColorThemes)
         {
            dataTableColorThemes.Rows.Add(theme, theme.ToString());
         }
         if (FCommunicator.ColorTheme == null) comboBoxThemes.SelectedValue = DBNull.Value;
         else comboBoxThemes.SelectedValue = FCommunicator.ColorTheme;

         comboBoxButtonsStyle.SelectedValue = FCommunicator.RenderMode;
         comboBoxFillStyle.SelectedValue = InternetCommunicator.Self.ColorFillStyle;
         comboBoxProxy.SelectedItem = Settings.Default.ProxyType;

         textBoxEmoPack.Text = Settings.Default.EmoPackPath;

         AssignPrivacy();
         RefreshDriverList();
      }
      private void RefreshDriverList()
      {
         listViewDrivers.Items.Clear();

         foreach (var drv in FCommunicator.ServiceDrivers)
         {
            ListViewItem item = new ListViewItem(drv.DefaultConfig.Service.ProtocolName, 0);

            item.Tag = drv;

            item.SubItems.Add(drv.AssemblyName);
            item.SubItems.Add(StringExt.Join(drv.Services.Where(s => s.Configurations.Count() > 0).Select(s => s.ToString()), ", "));

            listViewDrivers.Items.Add(item);
         }
      }

      private void buttonOk_Click(object sender, EventArgs e)
      {
         ApplySettings();
         FCommunicator.SaveSettings(false);
         Close();

         if (FNeedRestart && MessageBox.Show(Resources.S_For_this_changes_to_take_any_effect.Replace("<program>", FCommunicator.Title), Text,
             MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
         {
            Application.Restart();
         }
      }
      private void buttonCancel_Click(object sender, EventArgs e)
      {
         Close();
      }
      private void buttonEditCss_Click(object sender, EventArgs e)
      {
         FCommunicator.ShowCssEditWindow();
      }
      private void tabPagePrivacy_Click(object sender, EventArgs e)
      {
         tabPagePrivacy.Focus();
      }
      private void buttonInputFont_Click(object sender, EventArgs e)
      {
         fontDialog.Font = new Font(Settings.Default.InputFont, Settings.Default.InputFontSize);

         if (fontDialog.ShowDialog() == DialogResult.OK)
         {
            Settings.Default.InputFont = fontDialog.Font.Name;
            Settings.Default.InputFontSize = fontDialog.Font.Size;

            buttonInputFont.Font = fontDialog.Font;
            buttonInputFont.Text = fontDialog.Font.Name + "; " + fontDialog.Font.Size + "pt";
         }
      }
      private void panelBottom_Paint(object sender, PaintEventArgs e)
      {
         if (!AeroGlassVisible) FCommunicator.DrawTheme(FCommunicator.ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.PanelV);
      }
      private void comboBoxLanguage_Click(object sender, EventArgs e)
      {
         object selectedItem = comboBoxLanguage.SelectedItem;
         FCommunicator.RefreshSupportedCultures();
         comboBoxLanguage.Items.Clear();
         comboBoxLanguage.Items.AddRange(FCommunicator.SupportedCultures);
         comboBoxLanguage.SelectedItem = selectedItem;
      }
      private void service_SettingsChanged(object sender, EventArgs e)
      {
         RefreshDriverList();
      }
      private void buttonSelectEmoPack_Click(object sender, EventArgs e)
      {
         List<string> files = Shell.OpenFileDialog(Resources.S_Select_file, "", "ASL|*.asl");

         if (files.Count > 0) textBoxEmoPack.Text = files[0];
      }
      private void textBoxEmoPack_TextChanged(object sender, EventArgs e)
      {
         if (Settings.Default.EmoPackPath != textBoxEmoPack.Text) DelayedAction.Do(textBoxEmoPack, () =>
         {
            if (File.Exists(textBoxEmoPack.Text)) Settings.Default.EmoPackPath = textBoxEmoPack.Text;
         },
         500, true);
      }
      private void buttonDriverSettings_Click(object sender, EventArgs e)
      {
         if (listViewDrivers.SelectedItems.Count > 0)
         {
            CommunicationServiceObjectBase svcObj = (CommunicationServiceObjectBase)listViewDrivers.SelectedItems[0].Tag;
            svcObj.ShowDriverSettings("");
         }
      }
      private void buttonPrivacyDetails_Click(object sender, EventArgs e)
      {
         bool expand = !groupBoxUnknownUsersPolicy.Visible;

         tabPagePrivacy.SuspendLayout();

         groupBoxVipContactsPolicy.Visible = expand;
         groupBoxMyContactsPolicy.Visible = expand;
         groupBoxUnknownUsersPolicy.Visible = expand;

         tabPagePrivacy.ResumeLayout();

         buttonPrivacyDetails.Text = expand ? buttonPrivacyDetails.Text.Replace(">>", "<<") :
                                              buttonPrivacyDetails.Text.Replace("<<", ">>");
      }
      private void buttonInstallCulture_Click(object sender, EventArgs e)
      {
         contextMenuCultureList.Show(buttonInstallCulture, new Point(buttonInstallCulture.Size));
      }
      private void menuItemInstallCulture_Click(object sender, EventArgs e)
      {
         CultureInfo ci = (sender as MenuItem).Tag as CultureInfo;

         FCommunicator.CheckInstallation(CheckInstallationArg.Culture, ci.Name);
      }
      private void window_AeroGlassEffectChanged(object sender, EventArgs e)
      {
         checkBoxMaxAeroGlassEffect.Enabled = System.Custom.Drawing.AeroGlass.CompositionEnabled;

         if (AeroGlassVisible)
         {
            buttonOk.Top = 12;
            buttonCancel.Top = 12;
            buttonCancel.Left = panelTab.Left + panelTab.Width - buttonCancel.Width + 2;
         }
         else
         {
            buttonOk.Top = 9;
            buttonCancel.Top = 9;
            buttonCancel.Left = panelTab.Left + panelTab.Width - buttonCancel.Width - 2;
         }
         buttonOk.Left = buttonCancel.Left - buttonOk.Width - 6;
      }
      private void checkBoxTimeout_CheckedChanged(object sender, EventArgs e)
      {
         if (sender == checkBoxNaTimeout)
         {
            comboBoxNaTimeout.Enabled = checkBoxNaTimeout.Checked;
            comboBoxNaTimeout.Text = Settings.Default.Properties["NATimeout"].DefaultValue.ToString();
         }
         else if (sender == checkBoxAwayTimeout)
         {
            comboBoxAwayTimeout.Enabled = checkBoxAwayTimeout.Checked;
            comboBoxAwayTimeout.Text = Settings.Default.Properties["AwayTimeout"].DefaultValue.ToString();
         }
      }
      private void buttonCopySystemProxySettings_Click(object sender, EventArgs e)
      {
         try
         {
            RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings");

            bool proxyEnabled = key.GetValue("ProxyEnable", "0").ToString() == "1";

            List<string> proxyParams = key.GetValue("ProxyServer", "").ToString().Split('=', ':', ';').ToList();

            key.Close();

            if (proxyParams.Count >= 3)
            {
               int protoIndex = proxyParams.IndexOf("http");

               if (protoIndex < 0)
               {
                  protoIndex = proxyParams.IndexOf("https");

                  if (protoIndex < 0)
                  {
                     protoIndex = proxyParams.IndexOf("socks");
                  }
               }

               if (protoIndex >= 0)
               {
                  comboBoxProxy.SelectedItem = proxyEnabled ? proxyParams[protoIndex] : "None";
                  textBoxProxyHost.Text = proxyParams[protoIndex + 1];
                  textBoxProxyPort.Text = proxyParams[protoIndex + 2];
               }
            }
         }
         catch
         {
            //
         }
      }
      private void comboBoxThemes_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.ColorTheme = comboBoxThemes.SelectedValue.ToString();
         Settings.Default.ApplyStylesToMenus = FCommunicator.ColorTheme != null;
      }
      private void comboBoxLogStyle_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.SelectedLogStyleName = (string)comboBoxLogStyle.SelectedItem;
      }
      private void comboBoxSortStyle_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.ContactsSortStyle = (ContactsSortStyle)comboBoxSortStyle.SelectedValue;
      }
      private void comboBoxFillStyle_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.ColorFillStyle = (ColorFillStyle)comboBoxFillStyle.SelectedValue;
      }
      private void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "CustomLogStyle") comboBoxLogStyle.SelectedItem = Resources.S_Custom;
         else if (e.PropertyName == "SelectedLogStyleName") comboBoxLogStyle.SelectedItem = Settings.Default.SelectedLogStyleName;
      }
      private void communicator_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "ColorTheme") ColorTheme = FCommunicator.ColorTheme;
      }
      private void communicator_CheckingUpdates(object sender, InstallationCheckEventArgs e)
      {
         switch (e.State)
         {
            case InstallationState.CheckInProgress:
            {
               labelSearchCultureResults.Visible = true;
               labelSearchCultureResults.Text = Resources.S_Checking_updates;
               break;
            }
            case InstallationState.NoUpdates:
            {
               labelSearchCultureResults.Text = Resources.S_You_are_using_the_latest_version;
               break;
            }
            case InstallationState.InstallReady:
            {
               labelSearchCultureResults.ForeColor = Color.Blue;
               labelSearchCultureResults.Text = Resources.S_Updates_will_be_installed_automatically;
               break;
            }
            case InstallationState.ForcedInstall:
            {
               FCommunicator.Shutdown(true);
               Application.Restart();
               break;
            }
            default:
            {
               labelSearchCultureResults.Text = Resources.S_Updates_are_unavailable;
               break;
            }
         }
      }
      private void comboBoxButtonsStyle_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.RenderMode = comboBoxButtonsStyle.SelectedValue.ToString();
      }
      private void comboBoxMainWindowSide_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.MainWindowLeftSide = comboBoxMainWindowSide.SelectedIndex == 0;
      }
      private void comboBoxMainWindowLayout_SelectionChangeCommitted(object sender, EventArgs e)
      {
         Settings.Default.MainWindowLayout = (WindowDockType)comboBoxMainWindowLayout.SelectedValue;
      }

      private void checkBoxMessageRuleBlock_CheckedChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy) return;

         Settings.Default.UnknownUserMessageRule = checkBoxMessageRuleBlock.Checked ? PolicyRule.Block : PolicyRule.Allow;

         if (checkBoxMessageRuleBlock.Checked)
         {
            Settings.Default.UnknownUserInvitationRule = PolicyRule.Block;
            checkBoxFilterSpam.CheckState = CheckState.Indeterminate;
            checkBoxFilterSpam.Enabled = false;
         }
         else
         {
            checkBoxFilterSpam.CheckState = CheckState.Checked;
            checkBoxFilterSpam.Enabled = true;
         }

         AssignPrivacy();
      }
      private void checkBoxInvitationRuleBlock_CheckedChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy) return;

         Settings.Default.UnknownUserInvitationRule = checkBoxInvitationRuleBlock.Checked ? PolicyRule.Block : PolicyRule.Ask;
         //if (checkBoxInvitationRuleBlock.Checked) Settings.Default.UnknownUserMessageRule = PolicyRule.Block;

         AssignPrivacy();
      }
      private void comboBoxVipInvitationRule_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy || comboBoxVipInvitationRule.SelectedValue == null) return;

         Settings.Default.VipContactInvitationRule = (PolicyRule)Enum.Parse(typeof(PolicyRule), (string)comboBoxVipInvitationRule.SelectedValue);
      }
      private void comboBoxMyContactsMessageRule_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy || comboBoxMyContactsMessageRule.SelectedValue == null) return;

         Settings.Default.MyContactMessageRule = (PolicyRule)Enum.Parse(typeof(PolicyRule), (string)comboBoxMyContactsMessageRule.SelectedValue);
      }
      private void comboBoxUnknownUserMessageRule_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy || comboBoxUnknownUserMessageRule.SelectedValue == null) return;

         Settings.Default.UnknownUserMessageRule = (PolicyRule)Enum.Parse(typeof(PolicyRule), (string)comboBoxUnknownUserMessageRule.SelectedValue);

         AssignPrivacy();
      }
      private void comboBoxMyContactsInvitationRule_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy || comboBoxMyContactsInvitationRule.SelectedValue == null) return;

         Settings.Default.MyContactInvitationRule = (PolicyRule)Enum.Parse(typeof(PolicyRule), (string)comboBoxMyContactsInvitationRule.SelectedValue);
      }
      private void comboBoxUnknownUserInvitationRule_SelectedIndexChanged(object sender, EventArgs e)
      {
         if (FAssigningPrivacy || comboBoxUnknownUserInvitationRule.SelectedValue == null) return;

         Settings.Default.UnknownUserInvitationRule = (PolicyRule)Enum.Parse(typeof(PolicyRule), (string)comboBoxUnknownUserInvitationRule.SelectedValue);

         AssignPrivacy();
      }
   }
}
